// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Threading.Tasks;
using Azure;
using Azure.Core;
using Azure.Core.TestFramework;
using Azure.ResourceManager;
using Azure.ResourceManager.Models;
using Azure.ResourceManager.Resources;
using Azure.ResourceManager.PlanetaryComputer;
using Azure.ResourceManager.PlanetaryComputer.Models;
using NUnit.Framework;

namespace Azure.ResourceManager.PlanetaryComputer.Tests
{
    [TestFixture(true)]
    public class GeoCatalogCollectionTests : PlanetaryComputerManagementTestBase
    {
        // Add ExistingGeoCatalogName if you have a catalog to test against. This is for testing the GetGeoCatalog method.
        private const string ExistingGeoCatalogName = "";
        // Set the ResourceGroupName and Region to match your Azure environment.
        // Ensure the resource group exists in your subscription.
        private const string ResourceGroupName = "shakrao-test";
        private const string Region = "uksouth";

        public GeoCatalogCollectionTests(bool isAsync)
            : base(isAsync) // <-- Forces Record mode explicitly
        {
        }

        [Test]
        [RecordedTest]
        public async Task ListGeoCatalogsInResourceGroup()
        {
            SubscriptionResource subscription = await Client.GetDefaultSubscriptionAsync();
            ResourceGroupResource rg = await subscription.GetResourceGroups().GetAsync(ResourceGroupName);
            PlanetaryComputerGeoCatalogCollection collection = rg.GetPlanetaryComputerGeoCatalogs();

            int count = 0;
            await foreach (PlanetaryComputerGeoCatalogResource item in collection.GetAllAsync())
            {
                TestContext.WriteLine($"GeoCatalog: {item.Data.Name}");
                count++;
            }

            Assert.GreaterOrEqual(count, 0);
        }

        [Test]
        [RecordedTest]
        public async Task GetGeoCatalog()
        {
            if (string.IsNullOrEmpty(ExistingGeoCatalogName))
            {
                Assert.Inconclusive("No existing GeoCatalog name provided.");
                return;
            }

            PlanetaryComputerGeoCatalogCollection collection = await GetGeoCatalogCollectionAsync();
            PlanetaryComputerGeoCatalogResource catalog = await collection.GetAsync(ExistingGeoCatalogName);

            Assert.AreEqual(ExistingGeoCatalogName, catalog.Data.Name);
            Assert.AreEqual(Region.ToLowerInvariant(), catalog.Data.Location.ToString().ToLowerInvariant());
            TestContext.WriteLine($"Catalog URI: {catalog.Data.Properties.CatalogUri}");
        }

        [Test]
        [RecordedTest]
        public async Task CreateGeoCatalog()
        {
            string catalogName = Recording.GenerateAssetName("testcatalog-");
            PlanetaryComputerGeoCatalogCollection collection = await GetGeoCatalogCollectionAsync();
            PlanetaryComputerGeoCatalogData data = new PlanetaryComputerGeoCatalogData(new AzureLocation(Region))
            {
                Identity = new ManagedServiceIdentity(Azure.ResourceManager.Models.ManagedServiceIdentityType.UserAssigned)
                {
                    UserAssignedIdentities =
                    {
                        [new ResourceIdentifier($"/subscriptions/ac9a1867-7476-4346-bf8b-968370fe212c/resourceGroups/msi-test/providers/Microsoft.ManagedIdentity/userAssignedIdentities/msi-test-uk-1")] = new UserAssignedIdentity()
                    }
                },
                Properties = new PlanetaryComputerGeoCatalogProperties
                {
                    Tier = PlanetaryComputerGeoCatalogTier.Basic,
                    AutoGeneratedDomainNameLabelScope = AutoGeneratedDomainNameLabelScope.TenantReuse
                },
                Tags = { ["env"] = "test" }
            };

            ArmOperation<PlanetaryComputerGeoCatalogResource> operation = await collection.CreateOrUpdateAsync(WaitUntil.Completed, catalogName, data);
            PlanetaryComputerGeoCatalogResource result = operation.Value;

            Assert.AreEqual(catalogName, result.Data.Name);
            Assert.AreEqual(PlanetaryComputerGeoCatalogTier.Basic, result.Data.Properties.Tier);
            TestContext.WriteLine($"Created GeoCatalog: {result.Id}");
        }

        [Test]
        [RecordedTest]
        public async Task UpdateGeoCatalog()
        {
            string catalogName = Recording.GenerateAssetName("testcatalog-");
            PlanetaryComputerGeoCatalogCollection collection = await GetGeoCatalogCollectionAsync();

            PlanetaryComputerGeoCatalogData data = new PlanetaryComputerGeoCatalogData(new AzureLocation(Region))
            {
                Properties = new PlanetaryComputerGeoCatalogProperties
                {
                    Tier = PlanetaryComputerGeoCatalogTier.Basic,
                    AutoGeneratedDomainNameLabelScope = AutoGeneratedDomainNameLabelScope.TenantReuse
                },
                Tags = { ["env"] = "initial" }
            };

            ArmOperation<PlanetaryComputerGeoCatalogResource> createOp = await collection.CreateOrUpdateAsync(WaitUntil.Completed, catalogName, data);
            PlanetaryComputerGeoCatalogResource resource = createOp.Value;

            resource.Data.Tags["env"] = "updated";
            ArmOperation<PlanetaryComputerGeoCatalogResource> updateOp = await collection.CreateOrUpdateAsync(WaitUntil.Completed, catalogName, resource.Data);
            PlanetaryComputerGeoCatalogResource updated = updateOp.Value;

            Assert.AreEqual("updated", updated.Data.Tags["env"]);
            TestContext.WriteLine($"Updated GeoCatalog: {updated.Id}");
        }

        [Test]
        [RecordedTest]
        public async Task DeleteGeoCatalog()
        {
            string catalogName = Recording.GenerateAssetName("testcatalog-");
            PlanetaryComputerGeoCatalogCollection collection = await GetGeoCatalogCollectionAsync();

            PlanetaryComputerGeoCatalogData data = new PlanetaryComputerGeoCatalogData(new AzureLocation(Region))
            {
                Properties = new PlanetaryComputerGeoCatalogProperties
                {
                    Tier = PlanetaryComputerGeoCatalogTier.Basic,
                    AutoGeneratedDomainNameLabelScope = AutoGeneratedDomainNameLabelScope.TenantReuse
                },
                Tags = { ["env"] = "delete" }
            };

            ArmOperation<PlanetaryComputerGeoCatalogResource> createOp = await collection.CreateOrUpdateAsync(WaitUntil.Completed, catalogName, data);
            PlanetaryComputerGeoCatalogResource resource = createOp.Value;

            ArmOperation deleteOp = await resource.DeleteAsync(WaitUntil.Completed);
            Assert.IsTrue(deleteOp.HasCompleted);

            bool exists = await collection.ExistsAsync(catalogName);
            Assert.IsFalse(exists);
            TestContext.WriteLine($"Deleted GeoCatalog: {catalogName}");
        }

        [Test]
        [RecordedTest]
        public async Task ListGeoCatalogsBySubscription()
        {
            SubscriptionResource subscription = await Client.GetDefaultSubscriptionAsync();
            AsyncPageable<PlanetaryComputerGeoCatalogResource> catalogs = subscription.GetPlanetaryComputerGeoCatalogsAsync();

            int count = 0;
            await foreach (PlanetaryComputerGeoCatalogResource item in catalogs)
            {
                TestContext.WriteLine($"[Subscription List] GeoCatalog: {item.Data.Name}");
                count++;
            }
            Assert.GreaterOrEqual(count, 0);
        }
        [Test]
        [RecordedTest]
        public async Task CreateUpdateDeleteGeoCatalog()
        {
            Console.WriteLine($"[MODE] Test is running in: {TestEnvironment.Mode}");

            string catalogName = Recording.GenerateAssetName("testcatalog-");
            PlanetaryComputerGeoCatalogCollection collection = await GetGeoCatalogCollectionAsync();

            // Step 1: Create
            PlanetaryComputerGeoCatalogData data = new PlanetaryComputerGeoCatalogData(new AzureLocation(Region))
            {
                Properties = new PlanetaryComputerGeoCatalogProperties
                {
                    Tier = PlanetaryComputerGeoCatalogTier.Basic,
                    AutoGeneratedDomainNameLabelScope = AutoGeneratedDomainNameLabelScope.TenantReuse
                },
                Tags = { ["env"] = "initial" }
            };

            ArmOperation<PlanetaryComputerGeoCatalogResource> createOp = await collection.CreateOrUpdateAsync(WaitUntil.Completed, catalogName, data);
            PlanetaryComputerGeoCatalogResource resource = createOp.Value;

            Assert.AreEqual("initial", resource.Data.Tags["env"]);
            TestContext.WriteLine($"✅ Created GeoCatalog: {resource.Id}");

            // Step 2: Update
            resource.Data.Tags["env"] = "updated";
            ArmOperation<PlanetaryComputerGeoCatalogResource> updateOp = await collection.CreateOrUpdateAsync(WaitUntil.Completed, catalogName, resource.Data);
            PlanetaryComputerGeoCatalogResource updated = updateOp.Value;

            Assert.AreEqual("updated", updated.Data.Tags["env"]);
            TestContext.WriteLine($"🔄 Updated GeoCatalog: {updated.Id}");

            // Step 3: Delete
            ArmOperation deleteOp = await updated.DeleteAsync(WaitUntil.Completed);
            Assert.IsTrue(deleteOp.HasCompleted);

            bool exists = await collection.ExistsAsync(catalogName);
            Assert.IsFalse(exists);
            TestContext.WriteLine($"❌ Deleted GeoCatalog: {catalogName}");
        }

        private async Task<PlanetaryComputerGeoCatalogCollection> GetGeoCatalogCollectionAsync()
        {
            SubscriptionResource subscription = await Client.GetDefaultSubscriptionAsync();
            ResourceGroupResource rg = await subscription.GetResourceGroups().GetAsync(ResourceGroupName);
            return rg.GetPlanetaryComputerGeoCatalogs();
        }
    }
}
